#!/usr/bin/env python
# -*- coding:utf-8 -*- 
# Author: Jeokayne Ataier

'''
解决粘包的关键在于传输数据需要知晓数据大小
控制接收--接收完成之前while True循环
简单版：可以在传输数据时构建，先传输信息大小至对方（设置字节长度），再传输实际数据

利用struck将数据大小打包为4个字节的内容
'''
import json
import socket
import struct
from chardet.universaldetector import UniversalDetector

#获取编码格式(有可能返回空值，必须在下面进行返回值判断：if not dectector.result['encoding']:continue
def GetEncoding(str):
    dectector = UniversalDetector()
    dectector.feed(str)
    dectector.close()
    return dectector.result



#客户端主体代码
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",8882))
#信息收、发循环
while True:
    cmd = input(">>>")
    if not cmd:
        continue

    #1.构建可供传输数据头部信息
    header = {
        "size":len(cmd)
    }
    header_bytes = json.dumps(header).encode("utf-8")

    #2.传输头部信息长度（打包成4个字节传输）
    header_len = struct.pack("i",len(header_bytes))
    client.send(header_len)

    #3.传输头部信息
    client.send(header_bytes)

    #传输数据
    client.send(cmd.encode("utf-8"))
    '''
    客户端传输信息结束，接收服务端传回的信息
    '''


    #1.接收头部信息长度
    h1_len=struct.unpack("i",client.recv(4))[0]

    #2.接收头部信息，获取数据长度
    recv_h1_len = 0
    h1 = b""
    while recv_h1_len < h1_len:
        recv_h1 = client.recv(1024)
        h1 += recv_h1
        recv_h1_len += len(recv_h1)
    h1_dic = json.loads(h1.decode("utf-8"))
    data_size = h1_dic["size"]


    #3.接收数据

    recv_data_len = 0
    data = b""
    while recv_data_len < data_size:
        recv_data = client.recv(1024)
        data += recv_data
        recv_data_len+=len(recv_data)
    recv_encodings = GetEncoding(data)
    try:
        '''
        上面已经写好自动获取编码格式的代码，如果自己手动写decode，注意下面的编码：
        1.windows系统返回的byte需要用gbk解码decode
        2.Linux系统返回的byte需要用utf-8解码decode
        '''
        if not recv_encodings['encoding']:
            print(data.decode("utf-8"))
        else:
            print(data.decode(f"{recv_encodings['encoding']}"))
    except UnicodeError as e:
        print("返回值编码错误：",e)
        continue

client.close()